package com.macro.mall.tiny.common.example;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;
import java.util.Arrays;
import java.util.Base64;

/**
 * @author: i_kun
 * @Desc: o_。
 * @create: 2025-06-25 16:46
 */

public class HybridEncryptionExample {
    // 生成RSA密钥对（2048位）
    public static KeyPair generateRSAKeyPair() throws Exception {
        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
        // 安全标准
        keyGen.initialize(2048);
        return keyGen.generateKeyPair();
    }

    // 生成AES密钥（256位）
    public static SecretKey generateAESKey() throws Exception {
        KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        // 256位密钥
        keyGen.init(256);
        return keyGen.generateKey();
    }

    // 使用RSA公钥加密AES密钥
    public static byte[] encryptAESKeyWithRSA(PublicKey publicKey, SecretKey aesKey) throws Exception {
        // 推荐OAEP填充[1,4](@ref)
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(aesKey.getEncoded());
    }

    // 使用AES加密数据（GCM模式，提供认证和保密性）
    public static byte[] encryptDataWithAES(SecretKey aesKey, byte[] data) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        // 12字节IV
        byte[] iv = new byte[12];

        SecureRandom random = new SecureRandom();
        random.nextBytes(iv);
        // 128位认证标签
        GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
        cipher.init(Cipher.ENCRYPT_MODE, aesKey, gcmSpec);
        byte[] encrypted = cipher.doFinal(data);
        // 合并IV和密文（IV无需保密，但需唯一）
        byte[] result = new byte[iv.length + encrypted.length];
        System.arraycopy(iv, 0, result, 0, iv.length);
        System.arraycopy(encrypted, 0, result, iv.length, encrypted.length);
        return result;
    }

    // 使用RSA私钥解密AES密钥
    public static SecretKey decryptAESKeyWithRSA(PrivateKey privateKey, byte[] encryptedAESKey) throws Exception {
        Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedKey = cipher.doFinal(encryptedAESKey);
        return new SecretKeySpec(decryptedKey, "AES");
    }

    // 使用AES解密数据
    public static byte[] decryptDataWithAES(SecretKey aesKey, byte[] encryptedDataWithIV) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        // 拆分IV和密文（前12字节为IV）
        byte[] iv = Arrays.copyOfRange(encryptedDataWithIV, 0, 12);
        byte[] encryptedData = Arrays.copyOfRange(encryptedDataWithIV, 12, encryptedDataWithIV.length);
        GCMParameterSpec gcmSpec = new GCMParameterSpec(128, iv);
        cipher.init(Cipher.DECRYPT_MODE, aesKey, gcmSpec);
        return cipher.doFinal(encryptedData);
    }

    public static void main(String[] args) throws Exception {
        // 1. 生成密钥
        KeyPair rsaKeyPair = generateRSAKeyPair();
        SecretKey aesKey = generateAESKey();

        // 2. 加密流程
        String originalData = "敏感数据：Hello, Hybrid Encryption!";
        byte[] encryptedAESKey = encryptAESKeyWithRSA(rsaKeyPair.getPublic(), aesKey);
        byte[] encryptedData = encryptDataWithAES(aesKey, originalData.getBytes("UTF-8"));

        // 3. 解密流程
        SecretKey decryptedAESKey = decryptAESKeyWithRSA(rsaKeyPair.getPrivate(), encryptedAESKey);
        byte[] decryptedData = decryptDataWithAES(decryptedAESKey, encryptedData);

        // 4. 输出结果
        System.out.println("原始数据: " + originalData);
        System.out.println("解密数据: " + new String(decryptedData, "UTF-8"));
        System.out.println("\n加密细节:");
        System.out.println("RSA加密的AES密钥 (Base64): " + Base64.getEncoder().encodeToString(encryptedAESKey));
        System.out.println("AES加密数据 (Base64): " + Base64.getEncoder().encodeToString(encryptedData));
    }
}
